<!-- Copyright 2023 OpenObserve Inc.

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Affero General Public License for more details.

You should have received a copy of the GNU Affero General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
-->

<template>
  <q-layout
    view="hHh Lpr lff"
    :class="[store.state.printMode === true ? 'printMode' : '']"
  >
    <q-header
      :class="[store?.state?.theme == 'dark' ? 'dark-mode' : 'bg-white']"
    >
      <q-toolbar class="o2-bg-color">
        <div
          class="flex relative-position q-mr-sm"
          v-if="
            (config.isEnterprise == 'true' &&
              store.state.zoConfig.hasOwnProperty('custom_logo_text') &&
              store.state.zoConfig.custom_logo_text != '') ||
            (config.isEnterprise == 'true' &&
              store.state.zoConfig.hasOwnProperty('custom_logo_img') &&
              store.state.zoConfig.custom_logo_img != null)
          "
        >
          <span
            v-if="
              store.state.zoConfig.hasOwnProperty('custom_logo_text') &&
              store.state.zoConfig?.custom_logo_text != ''
            "
            class="text-h6 text-bold q-pa-none cursor-pointer q-mr-sm"
            @click="goToHome"
            >{{ store.state.zoConfig.custom_logo_text }}</span
          >
          <img
            v-if="
              store.state.zoConfig.hasOwnProperty('custom_logo_img') &&
              store.state.zoConfig?.custom_logo_img != null
            "
            :src="
              `data:image; base64, ` + store.state.zoConfig?.custom_logo_img
            "
            style="max-width: 150px; max-height: 31px"
          />
          <img
            v-if="store.state.zoConfig.custom_hide_self_logo == false"
            class="appLogo"
            loading="lazy"
            :src="
              store?.state?.theme == 'dark'
                ? getImageURL('images/common/openobserve_latest_dark_2.svg')
                : getImageURL('images/common/openobserve_latest_light_2.svg')
            "
            @click="goToHome"
          />
        </div>
        <div v-else class="flex relative-position q-mr-sm">
          <img
            class="appLogo"
            loading="lazy"
            :src="
              store?.state?.theme == 'dark'
                ? getImageURL('images/common/openobserve_latest_dark_2.svg')
                : getImageURL('images/common/openobserve_latest_light_2.svg')
            "
            @click="goToHome"
          />
        </div>

        <q-toolbar-title></q-toolbar-title>
        <div
          class="headerMenu float-left"
          v-if="store.state.organizationData.quotaThresholdMsg"
        >
          <div
            type="warning"
            icon="cloud"
            class="warning-msg"
            style="display: inline"
          >
            <q-icon name="warning" size="xs" class="warning" />{{
              store.state.organizationData.quotaThresholdMsg
            }}
          </div>
          <q-btn
            color="secondary"
            size="sm"
            style="display: inline; padding: 5px 10px"
            rounded
            borderless
            dense
            class="q-ma-xs"
            @click="router.replace('/billings/plans')"
            >Upgrade to PRO Plan</q-btn
          >
        </div>
        <q-btn
          v-if="
            config.isEnterprise == 'true' && store.state.zoConfig.ai_enabled
          "
          :ripple="false"
          @click="toggleAIChat"
          data-test="menu-link-ai-item"
          no-caps
          :borderless="true"
          flat
          dense
          class="o2-button ai-hover-btn q-px-sm q-py-sm"
          :class="store.state.isAiChatEnabled ? 'ai-btn-active' : ''"
          style="border-radius: 100%"
          @mouseenter="isHovered = true"
          @mouseleave="isHovered = false"
        >
          <div class="row items-center no-wrap tw-gap-2">
            <img :src="getBtnLogo" class="header-icon ai-icon" />
          </div>
        </q-btn>
        <div data-test="navbar-organizations-select" class="q-mx-sm row">
          <q-btn
            style="max-width: 250px"
            dense
            no-caps
            flat
            class="tw-text-ellipsis tw-overflow-hidden"
          >
            <div class="row items-center no-wrap full-width">
              <div class="col tw-truncate">
                {{ userClickedOrg?.label || "" }}
              </div>
              <q-icon name="arrow_drop_down" class="q-ml-xs" />
            </div>
            <q-menu
              anchor="bottom middle"
              self="top middle"
              class="organization-menu-o2"
            >
              <q-list data-test="organization-menu-list" style="width: 250px">
                <q-item data-test="organization-menu-item" style="padding: 0">
                  <q-item-section
                    data-test="organization-menu-item-section"
                    class="column"
                    style="padding: 0px"
                  >
                    <q-table
                      data-test="organization-menu-table"
                      :rows="filteredOrganizations"
                      :row-key="(row) => 'org_' + row.identifier"
                      :visible-columns="['label']"
                      hide-header
                      :pagination="{ rowsPerPage }"
                      :rows-per-page-options="[]"
                      class="org-table"
                    >
                      <template #top>
                        <div class="full-width">
                          <q-input
                            data-test="organization-search-input"
                            v-model="searchQuery"
                            data-cy="index-field-search-input"
                            filled
                            borderless
                            dense
                            clearable
                            debounce="1"
                            :placeholder="'Search Organization'"
                          >
                            <template #prepend>
                              <q-icon name="search" />
                            </template>
                          </q-input>
                        </div>
                      </template>

                      <template v-slot:body-cell-label="props">
                        <q-td
                          data-test="organization-menu-item-label"
                          :props="props"
                          class="org-list-item"
                        >
                          <q-item
                            data-test="organization-menu-item-label-item"
                            clickable
                            v-close-popup
                            dense
                            :class="{
                              'text-primary':
                                props.row.identifier ===
                                userClickedOrg?.identifier,
                            }"
                            @click="
                              selectedOrg = props.row;
                              updateOrganization();
                            "
                          >
                            <q-item-section>
                              <q-item-label
                                data-test="organization-menu-item-label-item-label"
                                class="tw-overflow-hidden tw-whitespace-nowrap tw-text-ellipsis tw-max-w-[230px]"
                              >
                                {{ props.row.label }}
                                <q-tooltip
                                  v-if="props.row.label.length > 35"
                                  anchor="bottom middle"
                                  self="top start"
                                >
                                  {{ props.row.label }}
                                </q-tooltip>
                              </q-item-label>
                            </q-item-section>
                          </q-item>
                        </q-td>
                      </template>
                      <template v-slot:no-data>
                        <div
                          data-test="organization-menu-no-data"
                          class="text-center q-pa-sm tw-w-full tw-flex tw-justify-center"
                        >
                          No organizations found
                        </div>
                      </template>
                    </q-table>
                  </q-item-section>
                </q-item>
              </q-list>
            </q-menu>
          </q-btn>
        </div>
        <!-- <div>
          <q-btn-dropdown
            data-test="language-dropdown"
            unelevated
            no-caps
            dense
            flat
            class="q-pa-xs q-ma-none"
            :icon="selectedLanguage.icon"
          >
            <q-list class="languagelist q-pa-none">
              <q-item
                data-test="language-dropdown-item"
                v-for="lang in langList"
                :key="lang.code"
                v-ripple="true"
                v-close-popup="true"
                clickable
                dense
                v-bind="lang"
                active-class="activeLang"
                @click="changeLanguage(lang)"
              >
                <q-item-section avatar>
                  <q-icon size="xs" :name="lang.icon"
class="padding-none" />
                </q-item-section>

                <q-item-section
                  :data-test="`language-dropdown-item-${lang.code}`"
                >
                  <q-item-label>{{ lang.label }}</q-item-label>
                </q-item-section>
              </q-item>
            </q-list>
          </q-btn-dropdown>
        </div> -->

        <ThemeSwitcher></ThemeSwitcher>

        <q-btn
          round
          flat
          dense
          :ripple="false"
          @click="openSlack"
          data-test="menu-link-slack-item"
        >
          <div class="row items-center no-wrap">
            <q-icon
              ><component :is="slackIcon" size="25px" class="header-icon"
            /></q-icon>
          </div>
          <q-tooltip anchor="top middle" self="bottom middle">
            {{ t("menu.slack") }}
          </q-tooltip>
        </q-btn>
        <q-btn round flat dense :ripple="false" data-test="menu-link-help-item">
          <div class="row items-center no-wrap">
            <q-icon
              name="help_outline"
              size="25px"
              class="header-icon"
            ></q-icon>
            <q-tooltip anchor="top middle" self="bottom middle">
              {{ t("menu.help") }}
            </q-tooltip>
          </div>

          <q-menu
            fit
            anchor="bottom right"
            self="top right"
            transition-show="jump-down"
            transition-hide="jump-up"
            class="header-menu-bar"
          >
            <q-list style="min-width: 250px">
              <div
                v-if="
                  config.isCloud !== 'true' &&
                  !store.state.zoConfig?.custom_hide_menus
                    ?.split(',')
                    ?.includes('openapi')
                "
              >
                <q-item clickable @click="navigateToOpenAPI(zoBackendUrl)">
                  <q-item-section>
                    <q-item-label>
                      {{ t(`menu.openapi`) }}
                    </q-item-label>
                  </q-item-section>
                </q-item>
                <q-separator />
              </div>
              <q-item clickable @click="navigateToDocs()">
                <q-item-section>
                  <q-item-label>
                    {{ t(`menu.docs`) }}
                  </q-item-label>
                </q-item-section>
              </q-item>
              <q-separator />
              <q-item to="/about" data-test="menu-link-about-item">
                <q-item-section>
                  <q-item-label>
                    {{ t(`menu.about`) }}
                  </q-item-label>
                </q-item-section>
              </q-item>
            </q-list>
          </q-menu>
        </q-btn>

        <q-btn
          data-test="menu-link-settings-item"
          round
          flat
          dense
          :ripple="false"
          @click="router.push({ name: 'settings' })"
        >
          <div class="row items-center no-wrap">
            <q-icon
              :name="outlinedSettings"
              size="25px"
              class="header-icon"
            ></q-icon>
          </div>
          <q-tooltip anchor="top middle" self="bottom middle">
            {{ t("menu.settings") }}
          </q-tooltip>
        </q-btn>

        <q-btn
          round
          flat
          dense
          :ripple="false"
          data-test="header-my-account-profile-icon"
        >
          <div class="row items-center no-wrap">
            <q-icon
              :name="user.picture ? user.picture : 'person'"
              size="25px"
              class="header-icon"
            ></q-icon>
            <q-tooltip anchor="top middle" self="bottom middle">
              {{
                user.given_name
                  ? user.given_name + " " + user.family_name
                  : user.email
              }}</q-tooltip
            >
          </div>

          <q-menu
            fit
            anchor="bottom right"
            self="top right"
            transition-show="jump-down"
            transition-hide="jump-up"
            class="header-menu-bar"
          >
            <q-list style="min-width: 250px">
              <q-item>
                <q-item-section avatar>
                  <q-icon
                    :name="user.picture ? user.picture : 'person'"
                    size="xs"
                  ></q-icon>
                </q-item-section>
                <q-item-section>
                  <q-item-label>{{
                    user.given_name
                      ? user.given_name + " " + user.family_name
                      : user.email
                  }}</q-item-label>
                </q-item-section>
              </q-item>
              <q-separator />
              <q-item clickable>
                <q-item-section avatar>
                  <q-icon size="xs" name="language" class="padding-none" />
                </q-item-section>
                <q-item-section>
                  <q-item-label class="tw-max-w-[150px]">{{
                    t("menu.language")
                  }}</q-item-label>
                </q-item-section>
                <q-item-section></q-item-section>
                <q-item-section side>
                  <div class="q-gutter-xs">
                    <q-icon
                      size="xs"
                      :name="selectedLanguage.icon"
                      class="padding-none"
                    />
                    <span
                      class="cursor-pointer vertical-bottom q-mt-sm selected-lang-label"
                      >{{ selectedLanguage.label }}</span
                    >
                  </div>
                </q-item-section>
                <q-item-section side style="padding-left: 0px">
                  <q-icon
                    class="icon-ley-arrow-right"
                    name="keyboard_arrow_right"
                  />
                </q-item-section>

                <q-menu
                  auto-close
                  anchor="top end"
                  self="top start"
                  data-test="language-dropdown-item"
                  class="header-menu-bar"
                >
                  <q-list>
                    <q-item
                      v-for="lang in langList"
                      :key="lang.code"
                      v-bind="lang"
                      dense
                      clickable
                      @click="changeLanguage(lang)"
                    >
                      <q-item-section avatar>
                        <q-icon
                          size="xs"
                          :name="lang.icon"
                          class="padding-none"
                        />
                      </q-item-section>

                      <q-item-section
                        :data-test="`language-dropdown-item-${lang.code}`"
                      >
                        <q-item-label>{{ lang.label }}</q-item-label>
                      </q-item-section>
                    </q-item>
                  </q-list>
                </q-menu>
              </q-item>
              <q-separator />
              <q-item
                data-test="menu-link-logout-item"
                v-ripple="true"
                v-close-popup="true"
                clickable
                @click="signout"
              >
                <q-item-section avatar>
                  <q-icon size="xs" name="exit_to_app" class="padding-none" />
                </q-item-section>
                <q-item-section>
                  <q-item-label>{{ t("menu.signOut") }}</q-item-label>
                </q-item-section>
              </q-item>
            </q-list>
          </q-menu>
        </q-btn>
      </q-toolbar>
    </q-header>

    <q-drawer
      v-model="drawer"
      show-if-above
      :width="80"
      :breakpoint="500"
      bordered
      class="o2-bg-color"
    >
      <q-list class="leftNavList">
        <menu-link
          v-for="nav in linksList"
          :key="nav.title"
          :link-name="nav.name"
          v-bind="{ ...nav, mini: miniMode }"
        />
      </q-list>
    </q-drawer>
    <div class="row full-height no-wrap">
      <!-- Left Panel -->
      <div
        class="col"
        v-show="isLoading"
        :style="{ width: store.state.isAiChatEnabled ? '75%' : '100%' }"
        :key="store.state.selectedOrganization?.identifier"
      >
        <q-page-container v-if="isLoading">
          <router-view v-slot="{ Component }">
            <component :is="Component" @sendToAiChat="sendToAiChat" />
          </router-view>
        </q-page-container>
      </div>

      <!-- Right Panel (AI Chat) -->

      <div
        class="col-auto"
        v-show="store.state.isAiChatEnabled && isLoading"
        style="width: 25%; max-width: 100%; min-width: 75px; z-index: 10"
        :class="
          store.state.theme == 'dark'
            ? 'dark-mode-chat-container'
            : 'light-mode-chat-container'
        "
      >
        <O2AIChat
          :header-height="82.5"
          :is-open="store.state.isAiChatEnabled"
          @close="closeChat"
          :aiChatInputContext="aiChatInputContext"
        />
      </div>
    </div>
    <q-dialog v-model="showGetStarted" maximized full-height>
      <GetStarted @removeFirstTimeLogin="removeFirstTimeLogin" />
    </q-dialog>
  </q-layout>
</template>

<script lang="ts">
import {
  QPage,
  QPageContainer,
  QLayout,
  QDrawer,
  QList,
  QItem,
  QItemLabel,
  QItemSection,
  QBtn,
  QBtnDropdown,
  QToolbarTitle,
  QHeader,
  QToolbar,
  QAvatar,
  QIcon,
  QSelect,
  useQuasar,
} from "quasar";
import MenuLink from "../components/MenuLink.vue";
import { useI18n } from "vue-i18n";
import {
  useLocalCurrentUser,
  useLocalOrganization,
  useLocalUserInfo,
  getImageURL,
  invalidateLoginData,
  getDueDays,
  trialPeriodAllowedPath,
} from "../utils/zincutils";

import {
  ref,
  defineComponent,
  KeepAlive,
  computed,
  onMounted,
  watch,
  markRaw,
  nextTick,
  onBeforeMount,
} from "vue";
import { useStore } from "vuex";
import { useRouter, RouterView } from "vue-router";
import config from "../aws-exports";

import { setLanguage } from "../utils/cookies";
import { getLocale } from "../locales";

import MainLayoutOpenSourceMixin from "@/mixins/mainLayout.mixin";
import MainLayoutCloudMixin from "@/enterprise/mixins/mainLayout.mixin";

import configService from "@/services/config";
import streamService from "@/services/stream";
import billings from "@/services/billings";
import ThemeSwitcher from "../components/ThemeSwitcher.vue";
import GetStarted from "@/components/login/GetStarted.vue";
import {
  outlinedHome,
  outlinedSearch,
  outlinedBarChart,
  outlinedAccountTree,
  outlinedDashboard,
  outlinedWindow,
  outlinedReportProblem,
  outlinedFilterAlt,
  outlinedPerson,
  outlinedFormatListBulleted,
  outlinedSettings,
  outlinedManageAccounts,
  outlinedDescription,
  outlinedCode,
} from "@quasar/extras/material-icons-outlined";
import SlackIcon from "@/components/icons/SlackIcon.vue";
import ManagementIcon from "@/components/icons/ManagementIcon.vue";
import organizations from "@/services/organizations";
import useStreams from "@/composables/useStreams";
import { openobserveRum } from "@openobserve/browser-rum";
import useSearchWebSocket from "@/composables/useSearchWebSocket";
import O2AIChat from "@/components/O2AIChat.vue";

let mainLayoutMixin: any = null;
if (config.isCloud == "true") {
  mainLayoutMixin = MainLayoutCloudMixin;
} else {
  mainLayoutMixin = MainLayoutOpenSourceMixin;
}

export default defineComponent({
  name: "MainLayout",
  mixins: [mainLayoutMixin],
  components: {
    "menu-link": MenuLink,
    "keep-alive": KeepAlive,
    "q-page": QPage,
    "q-page-container": QPageContainer,
    "q-layout": QLayout,
    "q-drawer": QDrawer,
    "q-list": QList,
    "q-item": QItem,
    "q-item-label": QItemLabel,
    "q-item-section": QItemSection,
    "q-btn": QBtn,
    "q-btn-dropdown": QBtnDropdown,
    "q-toolbar-title": QToolbarTitle,
    "q-header": QHeader,
    "q-toolbar": QToolbar,
    "router-view": RouterView,
    "q-avatar": QAvatar,
    "q-icon": QIcon,
    "q-select": QSelect,
    SlackIcon,
    ManagementIcon,
    ThemeSwitcher,
    O2AIChat,
    GetStarted,
  },
  methods: {
    navigateToDocs() {
      let docURL = "https://openobserve.ai/docs";
      if (
        this.config.isEnterprise == "true" &&
        this.store.state.zoConfig.custom_docs_url != ""
      ) {
        docURL = this.store.state.zoConfig.custom_docs_url;
      }
      window.open(docURL, "_blank");
    },
    navigateToOpenAPI(zoBackendUrl: string) {
      window.open(zoBackendUrl + "/swagger/index.html", "_blank");
    },
    signout() {
      this.closeSocket();

      if (config.isEnterprise == "true") {
        invalidateLoginData();
      }
      this.store.dispatch("logout");

      useLocalCurrentUser("", true);
      useLocalUserInfo("", true);

      this.$router.push("/logout");
    },
    goToHome() {
      this.$router.push("/");
    },
    changeLanguage(item: { code: string; label: string; icon: string }) {
      setLanguage(item.code);
      window.location.reload();
    },
  },
  setup() {
    const store: any = useStore();
    const router: any = useRouter();
    const { t } = useI18n();
    const $q = useQuasar();
    const miniMode = ref(false);
    const zoBackendUrl = store.state.API_ENDPOINT;
    const isLoading = ref(false);
    const { getStreams, resetStreams } = useStreams();
    const { closeSocket } = useSearchWebSocket();

    const isMonacoEditorLoaded = ref(false);
    const showGetStarted = ref(
      (localStorage.getItem("isFirstTimeLogin") ?? "false") === "true",
    );
    const isHovered = ref(false);
    const aiChatInputContext = ref("");
    const rowsPerPage = ref(10);
    const searchQuery = ref("");

    const filteredOrganizations = computed(() => {
      if (!searchQuery.value) return orgOptions.value;
      const toBeSearched = searchQuery.value.toLowerCase();
      return orgOptions.value.filter((org: any) =>
        org.label?.toLowerCase().includes(toBeSearched),
      );
    });

    let customOrganization = router.currentRoute.value.query.hasOwnProperty(
      "org_identifier",
    )
      ? router.currentRoute.value.query.org_identifier
      : undefined;
    const selectedOrg = ref(store.state.selectedOrganization);
    const userClickedOrg = ref(store.state.selectedOrganization);
    const excludeParentRedirect = [
      "pipeline",
      "functionList",
      "streamFunctions",
      "enrichmentTables",
      "alertList",
      "alertDestinations",
      "alertTemplates",
      "/ingestion/",
    ];

    const isActionsEnabled = computed(() => {
      return (
        (config.isEnterprise == "true" || config.isCloud == "true") &&
        store.state.zoConfig.actions_enabled
      );
    });

    const orgOptions = ref([{ label: Number, value: String }]);
    let slackURL = "https://short.openobserve.ai/community";
    if (
      config.isEnterprise == "true" &&
      store.state.zoConfig.custom_slack_url != ""
    ) {
      slackURL = store.state.zoConfig.custom_slack_url;
    }

    let user = store.state.userInfo;

    var linksList = ref([
      {
        title: t("menu.home"),
        icon: outlinedHome,
        link: "/",
        exact: true,
        name: "home",
      },
      {
        title: t("menu.search"),
        icon: outlinedSearch,
        link: "/logs",
        name: "logs",
      },
      {
        title: t("menu.metrics"),
        icon: outlinedBarChart,
        link: "/metrics",
        name: "metrics",
      },
      {
        title: t("menu.traces"),
        icon: outlinedAccountTree,
        link: "/traces",
        name: "traces",
      },
      {
        title: t("menu.rum"),
        icon: "devices",
        link: "/rum",
        name: "rum",
      },
      {
        title: t("menu.dashboard"),
        icon: outlinedDashboard,
        link: "/dashboards",
        name: "dashboards",
      },
      {
        title: t("menu.index"),
        icon: outlinedWindow,
        link: "/streams",
        name: "streams",
      },
      {
        title: t("menu.alerts"),
        icon: outlinedReportProblem,
        link: "/alerts",
        name: "alertList",
      },
      {
        title: t("menu.ingestion"),
        icon: outlinedFilterAlt,
        link: "/ingestion",
        name: "ingestion",
      },
      {
        title: t("menu.iam"),
        icon: outlinedManageAccounts,
        link: "/iam",
        display: store.state?.currentuser?.role == "admin" ? true : false,
        name: "iam",
      },
    ]);

    const langList = [
      {
        label: "English",
        code: "en-gb",
        icon: "img:" + getImageURL("images/language_flags/en-gb.svg"),
      },
      {
        label: "Türkçe",
        code: "tr-turk",
        icon: "img:" + getImageURL("images/language_flags/tr-turk.svg"),
      },
      {
        label: "简体中文",
        code: "zh-cn",
        icon: "img:" + getImageURL("images/language_flags/zh-cn.svg"),
      },
      {
        label: "Français",
        code: "fr",
        icon: "img:" + getImageURL("images/language_flags/fr.svg"),
      },
      {
        label: "Español",
        code: "es",
        icon: "img:" + getImageURL("images/language_flags/es.svg"),
      },
      {
        label: "Deutsch",
        code: "de",
        icon: "img:" + getImageURL("images/language_flags/de.svg"),
      },
      {
        label: "Italiano",
        code: "it",
        icon: "img:" + getImageURL("images/language_flags/it.svg"),
      },
      {
        label: "日本語",
        code: "ja",
        icon: "img:" + getImageURL("images/language_flags/ja.svg"),
      },
      {
        label: "한국어",
        code: "ko",
        icon: "img:" + getImageURL("images/language_flags/ko.svg"),
      },
      {
        label: "Nederlands",
        code: "nl",
        icon: "img:" + getImageURL("images/language_flags/nl.svg"),
      },
      {
        label: "Português",
        code: "pt",
        icon: "img:" + getImageURL("images/language_flags/pt.svg"),
      },
    ];

    onBeforeMount(() => {
      try {
        const url = new URL(window.location.href);
        const localOrg: any = useLocalOrganization();
        if (
          Object.keys(localOrg.value).length == 0 &&
          url.searchParams.get("org_identifier") != null
        ) {
          localOrg.value = {
            identifier: url.searchParams.get("org_identifier"),
            user_email: store.state.userInfo.email,
          };

          selectedOrg.value = localOrg.value;
          useLocalOrganization(localOrg.value);
          store.dispatch("setSelectedOrganization", localOrg.value);
        }
      } catch (error) {
        console.error("Error in onBeforeMount:", error);
      }
    });

    onMounted(async () => {
      filterMenus();

      // TODO OK : Clean get config functions which sets rum user and functions menu. Move it to common method.
      if (
        !store.state.zoConfig.hasOwnProperty("version") ||
        store.state.zoConfig.version == ""
      ) {
        getConfig();
      } else {
        if (config.isCloud == "false") {
          linksList.value = mainLayoutMixin
            .setup()
            .leftNavigationLinks(linksList, t);
          filterMenus();
        }
        await nextTick();
        // if rum enabled then setUser to capture session details.
        if (store.state.zoConfig.rum?.enabled) {
          setRumUser();
        }
      }
    });

    const updateActionsMenu = () => {
      if (isActionsEnabled.value) {
        const alertIndex = linksList.value.findIndex(
          (link) => link.name === "alertList",
        );

        const actionExists = linksList.value.some(
          (link) => link.name === "actionScripts",
        );

        if (alertIndex !== -1 && !actionExists) {
          linksList.value.splice(alertIndex + 1, 0, {
            title: t("menu.actions"),
            icon: outlinedCode,
            link: "/actions",
            name: "actionScripts",
          });
        }
      }
    };
    const splitterModel = ref(100);
    const selectedLanguage: any =
      langList.find((l) => l.code == getLocale()) || langList[0];

    const filterMenus = () => {
      updateActionsMenu();

      const disableMenus = new Set(
        store.state.zoConfig?.custom_hide_menus
          ?.split(",")
          ?.filter((val: string) => val?.trim()) || [],
      );

      store.dispatch("setHiddenMenus", disableMenus);

      linksList.value = linksList.value.filter((link: any) => {
        const hide = link.hide === undefined ? false : link.hide;

        return !disableMenus.has(link.name) && !hide;
      });
    };

    // additional links based on environment and conditions
    if (config.isCloud == "true") {
      linksList.value = mainLayoutMixin
        .setup()
        .leftNavigationLinks(linksList, t);
      filterMenus();
    } else {
      linksList.value.splice(7, 0, {
        title: t("menu.report"),
        icon: outlinedDescription,
        link: "/reports",
        name: "reports",
      });
    }

    //orgIdentifier query param exists then clear the localstorage and store.
    if (store.state.selectedOrganization != null) {
      if (
        mainLayoutMixin.setup().customOrganization != undefined &&
        mainLayoutMixin.setup().customOrganization !=
          store.state.selectedOrganization?.identifier
      ) {
        useLocalOrganization("");
        store.dispatch("setSelectedOrganization", {});
      }
    }

    const triggerRefreshToken = () => {
      const expirationTimeUnix = store.state.userInfo.exp;

      // Convert the expiration time to milliseconds
      const expirationTimeMilliseconds = expirationTimeUnix * 1000;

      // Get the current time in milliseconds
      const currentTimeMilliseconds = Date.now();

      // Calculate the time difference
      const timeUntilNextAPICall =
        expirationTimeMilliseconds - currentTimeMilliseconds - 100;

      // Convert the time difference from milliseconds to seconds
      const timeUntilNextAPICallInSeconds = timeUntilNextAPICall / 1000;

      // setTimeout(() => {
      //   mainLayoutMixin.setup().getRefreshToken();
      // }, timeUntilNextAPICallInSeconds);
    };

    //get refresh token for cloud environment
    if (store.state.hasOwnProperty("userInfo") && store.state.userInfo.email) {
      if (config.isCloud == "true") {
        triggerRefreshToken();
      }
    }

    const updateOrganization = async () => {
      resetStreams();
      store.dispatch("logs/resetLogs");
      store.dispatch("setIsDataIngested", false);
      const orgIdentifier = selectedOrg.value.identifier;
      const queryParams =
        router.currentRoute.value.path.indexOf(".logs") > -1
          ? router.currentRoute.value.query
          : {};
      router.push({
        path: router.currentRoute.value.path,
        query: {
          ...queryParams,
          org_identifier: orgIdentifier,
        },
      });
      useLocalOrganization(selectedOrg.value);
      store.dispatch("setSelectedOrganization", { ...selectedOrg.value });
      // setSelectedOrganization();
      // if (
      //   config.isCloud &&
      //   selectedOrg.value.subscription_type == config.freePlan
      // ) {
      //   await billings
      //     .list_subscription(selectedOrg.value.identifier)
      //     .then(async (res: any) => {
      //       if (res.data.data.length == 0) {
      //         router.push({ name: "plans" });
      //       } else if (
      //         res.data.data.CustomerBillingObj.customer_id == null ||
      //         res.data.data.CustomerBillingObj.customer_id == ""
      //       ) {
      //         router.push({ name: "plans" });
      //       } else {
      //         await verifyStreamExist(selectedOrg.value);
      //       }
      //     });
      // } else {
      if (
        store.state.zoConfig.hasOwnProperty(
          "restricted_routes_on_empty_data",
        ) &&
        store.state.zoConfig.restricted_routes_on_empty_data == true &&
        store.state.organizationData.isDataIngested == false
      ) {
        await verifyStreamExist(selectedOrg.value);
      }
    };

    const verifyStreamExist = async (selectedOrgData: any) => {
      await getStreams("", false).then((response: any) => {
        store.dispatch("setSelectedOrganization", {
          ...selectedOrgData,
        });
        if (response.list.length == 0) {
          store.dispatch("setIsDataIngested", false);
          $q.notify({
            type: "warning",
            message:
              "You haven't initiated the data ingestion process yet. To explore other pages, please start the data ingestion.",
            timeout: 5000,
          });
          router.push({ name: "ingestion" });
        } else {
          store.dispatch("setIsDataIngested", true);
        }
      });
    };

    const setSelectedOrganization = async () => {
      try {
        customOrganization = router.currentRoute.value.query.hasOwnProperty(
          "org_identifier",
        )
          ? router.currentRoute.value.query.org_identifier
          : "";
        let tempDefaultOrg = {};
        let localOrgFlag = false;
        const url = new URL(window.location.href);
        if (store.state.organizations?.length > 0) {
          const localOrg: any = useLocalOrganization();
          if (
            Object.keys(localOrg.value).length == 0 &&
            url.searchParams.get("org_identifier") != null
          ) {
            localOrg.value = {
              identifier: url.searchParams.get("org_identifier"),
              user_email: store.state.userInfo.email,
            };
          }
          orgOptions.value = store.state.organizations
            .map(
              (data: {
                id: any;
                name: any;
                type: any;
                identifier: any;
                UserObj: any;
                ingest_threshold: number;
                search_threshold: number;
                CustomerBillingObj: { subscription_type: string; note: string };
                status: string;
              }) => {
                const optiondata: any = {
                  label: data.name,
                  id: data.id,
                  identifier: data.identifier,
                  user_email: store.state.userInfo.email,
                  ingest_threshold: data.ingest_threshold,
                  search_threshold: data.search_threshold,
                  subscription_type: data.hasOwnProperty("CustomerBillingObj")
                    ? data.CustomerBillingObj.subscription_type
                    : "",
                  status: data.status,
                  note: data.hasOwnProperty("CustomerBillingObj")
                    ? data.CustomerBillingObj.note
                    : "",
                };

                if (
                  config.isCloud == "true" &&
                  localOrg.value?.identifier == data?.identifier &&
                  (customOrganization == "" || customOrganization == undefined)
                ) {
                  // localOrg.value.subscription_type =
                  //   data.CustomerBillingObj.subscription_type;
                  // useLocalOrganization(localOrg.value);
                  useLocalOrganization(optiondata);
                }

                if (
                  localOrg.value.identifier == data.identifier ||
                  url.searchParams.get("org_identifier") == data.identifier
                ) {
                  localOrgFlag = true;
                }

                if (
                  (Object.keys(selectedOrg.value).length == 0 &&
                    data.type == "default" &&
                    store.state.userInfo.email == data.UserObj.email &&
                    (customOrganization == "" ||
                      customOrganization == undefined)) ||
                  (store.state.organizations?.length == 1 &&
                    (customOrganization == "" ||
                      customOrganization == undefined))
                ) {
                  selectedOrg.value = localOrg.value
                    ? localOrg.value
                    : optiondata;
                  useLocalOrganization(optiondata);
                  store.dispatch("setSelectedOrganization", optiondata);
                } else if (data.identifier == customOrganization) {
                  selectedOrg.value = optiondata;
                  useLocalOrganization(optiondata);
                  store.dispatch("setSelectedOrganization", optiondata);
                }

                if (data.type == "default") {
                  tempDefaultOrg = optiondata;
                }

                return optiondata;
              },
            )
            .sort((a: any, b: any) => a.label.localeCompare(b.label));
        }

        if (localOrgFlag == false) {
          selectedOrg.value = tempDefaultOrg;
          useLocalOrganization(tempDefaultOrg);
          store.dispatch("setSelectedOrganization", tempDefaultOrg);
        }

        if (
          Object.keys(selectedOrg.value).length == 0 &&
          store.state.organizations.length > 0
        ) {
          let data = store.state.organizations[0];
          let optiondata = {
            label: data.name,
            id: data.id,
            identifier: data.identifier,
            user_email: store.state.userInfo.email,
            ingest_threshold: data.ingest_threshold,
            search_threshold: data.search_threshold,
            subscription_type: data.hasOwnProperty("CustomerBillingObj")
              ? data.CustomerBillingObj.subscription_type
              : "",
            status: data.status,
            note: data.hasOwnProperty("CustomerBillingObj")
              ? data.CustomerBillingObj.note
              : "",
          };
          selectedOrg.value = optiondata;
          useLocalOrganization(optiondata);
          store.dispatch("setSelectedOrganization", optiondata);
        }

        if (router.currentRoute.value.query.action == "subscribe") {
          router.push({
            name: "plans",
            query: {
              org_identifier: selectedOrg.value.identifier,
            },
          });
        }

        if (
          Object.keys(selectedOrg.value).length > 0 &&
          selectedOrg.value.identifier != "" &&
          selectedOrg.value.identifier != undefined
        ) {
          await getOrganizationSettings();
          isLoading.value = true;
        }
      } catch (error) {
        console.error("Error in setSelectedOrganization:", error);
      }
    };

    // get organizations settings on first load and identifier change
    const getOrganizationSettings = async () => {
      try {
        //get organizations settings
        const orgSettings: any = await organizations.get_organization_settings(
          store.state?.selectedOrganization?.identifier,
        );

        //set settings in store
        //scrape interval will be in number
        store.dispatch("setOrganizationSettings", {
          scrape_interval: orgSettings?.data?.data?.scrape_interval ?? 15,
          span_id_field_name:
            orgSettings?.data?.data?.span_id_field_name ?? "spanId",
          trace_id_field_name:
            orgSettings?.data?.data?.trace_id_field_name ?? "traceId",
          toggle_ingestion_logs:
            orgSettings?.data?.data?.toggle_ingestion_logs ?? false,
          enable_websocket_search:
            orgSettings?.data?.data?.enable_websocket_search ?? false,
          enable_streaming_search:
            orgSettings?.data?.data?.enable_streaming_search ?? false,
          streaming_aggregation_enabled:
            orgSettings?.data?.data?.streaming_aggregation_enabled ?? false,
          free_trial_expiry: orgSettings?.data?.data?.free_trial_expiry ?? "",
        });

        if (
          orgSettings?.data?.data?.free_trial_expiry != null &&
          orgSettings?.data?.data?.free_trial_expiry != ""
        ) {
          const trialDueDays = getDueDays(
            orgSettings?.data?.data?.free_trial_expiry,
          );
          if (
            trialDueDays <= 0 &&
            trialPeriodAllowedPath.indexOf(router.currentRoute.value.name) == -1
          ) {
            router.push({
              name: "plans",
              query: {
                org_identifier: selectedOrg.value.identifier,
              },
            });
          }
        }
      } catch (error) {
        console.error("Error in getOrganizationSettings:", error);
      }
      return;
    };

    /**
     * Get configuration from the backend.
     * @return {"version":"","instance":"","commit_hash":"","build_date":"","default_fts_keys":["field1","field2"],"telemetry_enabled":true,"default_functions":[{"name":"function name","text":"match_all('v')"}}
     * @throws {Error} If the request fails.
     */
    const getConfig = async () => {
      await configService
        .get_config()
        .then(async (res: any) => {
          if (config.isCloud == "false") {
            linksList.value = mainLayoutMixin
              .setup()
              .leftNavigationLinks(linksList, t);
          }

          store.dispatch("setConfig", res.data);
          await nextTick();

          filterMenus();
          // if rum enabled then setUser to capture session details.
          if (res.data.rum.enabled) {
            setRumUser();
          }
        })
        .catch((error) => console.log(error));
    };

    if (config.isCloud == "true") {
      mainLayoutMixin.setup().getDefaultOrganization(store);
    }

    const setRumUser = () => {
      if (store.state.zoConfig?.rum?.enabled == true) {
        const userInfo = store.state.userInfo;
        openobserveRum.setUser({
          name: userInfo.given_name + " " + userInfo.family_name,
          email: userInfo.email,
        });
      }
    };

    const prefetch = () => {
      const href = "/web/assets/editor.api.v1.js";
      const existingLink = document.querySelector(
        `link[rel="prefetch"][href="${href}"]`,
      );

      if (!existingLink) {
        // Create a new link element
        isMonacoEditorLoaded.value = true;
        const link = document.createElement("link");
        link.rel = "prefetch";
        link.href = href;
        document.head.appendChild(link);
      }
    };

    const expandMenu = () => {
      // miniMode.value = false;
      if (!isMonacoEditorLoaded.value) prefetch();
    };

    const openSlack = () => {
      window.open(slackURL, "_blank");
    };

    const toggleAIChat = () => {
      const isEnabled = !store.state.isAiChatEnabled;
      store.dispatch("setIsAiChatEnabled", isEnabled);
      window.dispatchEvent(new Event("resize"));
    };

    const closeChat = () => {
      store.dispatch("setIsAiChatEnabled", false);
      window.dispatchEvent(new Event("resize"));
    };

    const getBtnLogo = computed(() => {
      if (isHovered.value || store.state.isAiChatEnabled) {
        return getImageURL("images/common/ai_icon_dark.svg");
      }

      return store.state.theme === "dark"
        ? getImageURL("images/common/ai_icon_dark.svg")
        : getImageURL("images/common/ai_icon.svg");
    });
    //this will be the function used to cancel the get started dialog and remove the isFirstTimeLogin from local storage
    //this will be called from the get started component whenever users clicks on the submit button
    const removeFirstTimeLogin = (val: boolean) => {
      showGetStarted.value = val;
      localStorage.removeItem("isFirstTimeLogin");
    };

    const sendToAiChat = (value: any) => {
      if (!store.state.isAiChatEnabled) {
        store.dispatch("setIsAiChatEnabled", true);
      }
      //here we reset the value befoere setting it because if user clears the input then again click on the same value it wont trigger the watcher that is there in the child component
      //so to force trigger we do this
      aiChatInputContext.value = "";
      nextTick(() => {
        aiChatInputContext.value = value;
      });
    };
    //this is the used to set the selected org to the user clicked org because all the operations are happening on the selected org
    //to make sync with the user clicked org
    //we dont need search query after selectedOrg has been changed so resetting it
    watch(
      selectedOrg,
      (newVal) => {
        userClickedOrg.value = newVal;
        searchQuery.value = "";
      },
      { immediate: true },
    );

    return {
      t,
      router,
      store,
      config,
      langList,
      selectedLanguage,
      linksList,
      selectedOrg,
      orgOptions,
      leftDrawerOpen: false,
      miniMode,
      user,
      zoBackendUrl,
      isLoading,
      getImageURL,
      updateOrganization,
      setSelectedOrganization,
      getOrganizationSettings,
      resetStreams,
      triggerRefreshToken,
      prefetch,
      expandMenu,
      slackIcon: markRaw(SlackIcon),
      openSlack,
      outlinedSettings,
      closeSocket,
      splitterModel,
      toggleAIChat,
      closeChat,
      getBtnLogo,
      isHovered,
      showGetStarted,
      removeFirstTimeLogin,
      sendToAiChat,
      aiChatInputContext,
      userClickedOrg,
      searchQuery,
      filteredOrganizations,
      rowsPerPage,
      verifyStreamExist,
      filterMenus,
      updateActionsMenu,
      getConfig,
      setRumUser,
    };
  },
  computed: {
    changeOrganization() {
      return this.store?.state?.organizations;
    },
    changeOrganizationIdentifier() {
      return this.store?.state?.selectedOrganization?.identifier;
    },
    forceFetchOrganization() {
      return this.router?.currentRoute?.value?.query?.update_org;
    },
    changeUserInfo() {
      return this.store?.state?.userInfo;
    },
  },
  watch: {
    forceFetchOrganization() {
      mainLayoutMixin.setup().getDefaultOrganization(this.store);
    },
    changeOrganization: {
      handler() {
        this.setSelectedOrganization();
      },
      deep: true,
      immediate: true,
    },
    async changeOrganizationIdentifier() {
      this.isLoading = false;
      this.resetStreams();
      this.store.dispatch("setOrganizationPasscode", "");
      this.store.dispatch("resetOrganizationData", {});

      await this.getOrganizationSettings();

      this.isLoading = true;
      // Find the matching organization from orgOptions
      const matchingOrg = this.orgOptions.find(
        (org) =>
          org.identifier === this.store.state.selectedOrganization.identifier,
      );

      if (matchingOrg) {
        this.selectedOrg = matchingOrg;
      }
    },
    changeUserInfo(newVal) {
      if (JSON.stringify(newVal) != "{}") {
        this.triggerRefreshToken();
      }
    },
  },
});
</script>

<style lang="scss">
@import "../styles/app.scss";

.printMode {
  .q-header {
    display: none;
  }

  .q-drawer {
    display: none;
  }

  .q-page-container {
    padding-left: 0px !important;
  }
}

.warning-msg {
  background-color: var(--q-warning);
  padding: 5px;
  border-radius: 5px;
}

.alert-msg {
  background-color: var(--q-alert);
  padding: 5px;
  border-radius: 5px;
}

.q-header .q-btn-dropdown__arrow {
  margin-left: -4px;
}

.q-header {
  color: unset;
  @extend .border-bottom;

  .beta-text {
    font-size: 11px;
    right: 1px;
    bottom: -9px;
  }

  .appLogo {
    width: 120px;
    max-width: 150px;
    max-height: 31px;
    cursor: pointer;

    &__mini {
      margin-right: 0.25rem;
      // margin-left: 0.25rem;
      height: 30px;
      width: 30px;
    }
  }
}

.q-toolbar {
  min-height: 40px;
}

.headerMenu {
  margin-right: 1rem;

  .block {
    font-weight: 700;
    color: #404040;
  }
}

.q-item {
  min-height: 30px;
  padding: 8px 8px;
}

.o2-bg-color {
  background-color: rgba(89, 96, 178, 0.08);
}

.q-list {
  &.leftNavList {
    padding-bottom: 0px;

    .q-item {
      margin: 5px 5px 5px 5px;
      display: list-item;
      text-align: center;
      list-style: none;
      padding: 5px 2px;
      border-radius: 5px;

      .q-icon {
        height: 1.5rem;
        width: 1.5rem;
      }

      &.q-router-link--active {
        .q-icon img {
          filter: brightness(100);
        }

        .q-item__label {
          color: white;
        }
        color: white;
      }

      &__label {
        font-size: 12px;
        font-weight: 600;
        color: grey;
      }
    }
  }

  .flagIcon img {
    border-radius: 3px;
    object-fit: cover;
    display: block;
    height: 16px;
    width: 24px;
  }

  .q-item {
    &__section {
      &--avatar {
        padding-right: 0px !important;
        min-width: 1.5rem;
        display: list-item;
        text-align: center;
        list-style: none;
      }
    }

    &__label {
      font-weight: 400;
    }

    &.activeLang {
      &__label {
        font-weight: 600;
        color: $primary;
      }
    }
  }
}

.userInfo {
  align-items: flex-start;
  flex-direction: column;
  margin-left: 0.875rem;
  margin-right: 1rem;
  display: flex;

  .userName {
    line-height: 1.25rem;
    font-weight: 700;
  }

  .userRole {
    font-size: 0.75rem;
    line-height: 1rem;
    color: #565656;
    font-weight: 600;
  }
}

.headerMenu {
  margin-right: 1rem;

  .block {
    font-weight: 700;
    color: #404040;
  }
}
.q-list {
  &.leftNavList {
    .q-item {
      .q-icon {
        height: 1.5rem;
        width: 1.5rem;
      }

      &.q-router-link--active {
        .q-icon img {
          filter: brightness(100);
        }
      }
    }
  }

  .flagIcon img {
    border-radius: 3px;
    object-fit: cover;
    display: block;
    height: 16px;
    width: 24px;
  }

  .q-item {
    &__section {
      &--avatar {
        padding-right: 0.875rem;
        min-width: 1.5rem;
      }
    }

    &__label {
      font-weight: 400;
    }

    &.activeLang {
      &__label {
        font-weight: 600;
        color: $primary;
      }
    }
  }
}

.userInfo {
  align-items: flex-start;
  flex-direction: column;
  margin-left: 0.875rem;
  margin-right: 1rem;
  display: flex;

  .userName {
    line-height: 1.25rem;
    font-weight: 700;
  }

  .userRole {
    font-size: 0.75rem;
    line-height: 1rem;
    color: #565656;
    font-weight: 600;
  }
}

.dark-mode {
  background-color: $dark-page;
}

.languagelist {
  .q-item {
    padding: 4px 8px;
  }
}

.text-powered-by {
  float: left;
  display: inline-block;
  position: absolute;
  margin-top: 16px;
  margin-left: 0px;
}

.custom-text-logo {
  display: inline-block;
  float: left;
  position: absolute;
  margin-left: 72px !important;
  margin-top: 16px !important;
  width: 80px !important;
}

.header-icon {
  opacity: 0.7;
}

body.ai-chat-open {
  .q-layout {
    width: 75%;
    transition: width 0.3s ease;
  }
}

.q-layout {
  width: 100%;
  transition: width 0.3s ease;
}

.o2-button {
  border-radius: 4px;
  padding: 0px 8px;
  color: white;
}
.dark-mode-chat-container {
  border-left: 1.5px solid #232323ff;
}
.light-mode-chat-container {
  border-left: 1.5px solid #f7f7f7;
}

.ai-btn-active {
  background-color: #5960b2 !important;
}
.ai-hover-btn {
  transition: background-color 1s ease;
}

.ai-hover-btn:hover {
  background-color: #5960b2;
}

.ai-icon {
  transition: transform 0.6s ease;
}

.ai-hover-btn:hover .ai-icon {
  transform: rotate(-180deg);
}

.organization-menu-o2 {
  .org-table {
    td {
      padding: 0;
      height: 25px !important;
      min-height: 25px !important;
    }

    .q-table__control {
      margin: 0px !important;
      width: 100% !important;
      text-align: right;
    }

    .q-table__bottom {
      padding: 0px !important;
      min-height: 35px;

      .q-table__control {
        padding: 0px 10px !important;
      }
    }

    .q-table__top {
      padding: 0px !important;
      margin: 0px !important;
      left: 0px;
      width: 100%;

      .q-table__separator {
        display: none;
      }

      .q-table__control {
        padding: 0px !important;
      }
    }

    .q-field--filled .q-field__control {
      padding: 0px 5px !important;
    }

    .saved-view-item {
      padding: 4px 5px 4px 10px !important;
    }

    .q-item__section--main ~ .q-item__section--side {
      padding-left: 5px !important;
    }
    .org-table {
      .text-primary {
        color: var(--q-primary) !important;
        font-weight: 500;
        background: rgba(89, 96, 178, 0.08);
      }
    }
  }
  .q-menu {
    .q-input {
      .q-field__control {
        height: 40px;
      }

      input {
        font-size: 14px;
      }
    }
  }
}
</style>
